package org.beian.fmmall.service.Impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.beian.fmmall.VO.ResStatus;
import org.beian.fmmall.VO.ResultVO;
import org.beian.fmmall.beans.*;
import org.beian.fmmall.dao.ProductImgMapper;
import org.beian.fmmall.dao.ProductMapper;
import org.beian.fmmall.dao.ProductParamsMapper;
import org.beian.fmmall.dao.ProductSkuMapper;
import org.beian.fmmall.service.ProductService;
import org.beian.fmmall.utils.PageHelper;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.io.IOException;
import java.util.*;

@Service
public class ProductServiceImpl implements ProductService {
    @Autowired
    private RestHighLevelClient restHighLevelClient;
    @Autowired
    private ProductMapper productMapper;
    @Autowired
    private ProductImgMapper productImgMapper;
    @Autowired
    private ProductSkuMapper productSkuMapper;
    @Autowired
    private ProductParamsMapper productParamsMapper;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    private ObjectMapper objectMapper=new ObjectMapper();
    @Override
    public ResultVO listRecommendProducts() {
        List<ProductVO> productVOS = productMapper.selectRecommendProducts();
        return new ResultVO(ResStatus.OK,"success",productVOS);
    }

    @Override
    public ResultVO getProductBasicInfo(String productId) {
        try {
            String productInfo = (String) stringRedisTemplate.boundHashOps("products").get(productId);
            if(productInfo!=null){
                Product product = objectMapper.readValue(productInfo, Product.class);
                String productImgs = (String) stringRedisTemplate.boundHashOps("productImgs").get(productId);
                JavaType javaType = objectMapper.getTypeFactory().constructParametricType(ArrayList.class, ProductImg.class);
                List<ProductImg> productImgList= objectMapper.readValue(productImgs, javaType);
                String productSkus = (String) stringRedisTemplate.boundHashOps("productSkus").get(productId);
                JavaType javaType2 = objectMapper.getTypeFactory().constructParametricType(ArrayList.class, ProductSku.class);
                List<ProductImg> productSkuList= objectMapper.readValue(productSkus, javaType2);
                HashMap<String,Object> map=new HashMap<>();
                map.put("product",product);
                map.put("productImgs",productImgList);
                map.put("productSkus",productSkuList);
                return new ResultVO(ResStatus.OK,"success",map);
            }else{
                Example example = new Example(Product.class);
                Example.Criteria criteria = example.createCriteria();
                criteria.andEqualTo("productId",productId);
                List<Product> products = productMapper.selectByExample(example);
                if(products.size()>0){
                    Product product = products.get(0);
                    String jsonstr = objectMapper.writeValueAsString(product);
                    stringRedisTemplate.boundHashOps("products").put(productId,jsonstr);

                    Example example1 = new Example(ProductImg.class);
                    Example.Criteria criteria1 = example1.createCriteria();
                    criteria1.andEqualTo("itemId",productId);
                    List<ProductImg> productImgs = productImgMapper.selectByExample(example1);
                    stringRedisTemplate.boundHashOps("productImgs").put(productId,objectMapper.writeValueAsString(productImgs));

                    Example example2 = new Example(ProductSku.class);
                    Example.Criteria criteria2 = example2.createCriteria();
                    criteria2.andEqualTo("productId",productId);
                    criteria2.andEqualTo("status",1);
                    List<ProductSku> productSkus = productSkuMapper.selectByExample(example2);
                    stringRedisTemplate.boundHashOps("productSkus").put(productId,objectMapper.writeValueAsString(productSkus));
                    HashMap<String,Object> map=new HashMap<>();
                    map.put("product",products.get(0));
                    map.put("productImgs",productImgs);
                    map.put("productSkus",productSkus);
                    return new ResultVO(ResStatus.OK,"success",map);
                }else{
                    return new ResultVO(ResStatus.NO,"查询的商品不存在！",null);
                }

            }
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public ResultVO getProductParamsById(String productId) {
        Example example = new Example(ProductParams.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("productId", productId);
        List<ProductParams> productParams = productParamsMapper.selectByExample(example);
        if(productParams.size()>0){
            return new ResultVO(ResStatus.OK,"success",productParams.get(0));
        }else{
            return new ResultVO(ResStatus.NO,"可能是三五食品",null);
        }
    }

    @Override
    public ResultVO getProductByCategoryId(int cid, int pageNum, int limit) {
        int start=(pageNum-1)*limit;
        List<ProductByCategoryVO> list = productMapper.selectProsByCategory(cid, start, limit);
        Example example = new Example(Product.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("categoryId",cid);
        int count = productMapper.selectCountByExample(example);
        int pageCounts=count%limit==0?count%limit:count%limit+1;
        PageHelper<ProductByCategoryVO> pageHelper = new PageHelper<>(count,pageCounts,list);
        return new ResultVO(ResStatus.OK,"success",pageHelper);
    }

    @Override
    public ResultVO getBrandByCategoryId(int cid) {
        List<String> list = productMapper.selectBrandByCategoryId(cid);
        return new ResultVO(ResStatus.OK,"success",list);
    }

    @Override
    public ResultVO getBrandBySearch(String keyWord) {
        List<String> list = productMapper.selectBrandBySearch(keyWord);
        return new ResultVO(ResStatus.OK,"success",list);
    }

    @Override
    public ResultVO getProductsByBrand(int cid, int pageNum, int limit, String brand) {
        int start=(pageNum-1)*limit;
        List<ProductByCategoryVO> list = productMapper.selectProsByBrands(cid, start, limit,brand);
        int count=productMapper.selectProsCountByBrand(cid, brand);
        int pageCounts=count%limit==0?count%limit:count%limit+1;
        PageHelper<ProductByCategoryVO> pageHelper = new PageHelper<>(count,pageCounts,list);
        return new ResultVO(ResStatus.OK,"success",pageHelper);
    }

    @Override
    public ResultVO getProductsBySearch(int pageNum, int limit, String keyWord) {
        PageHelper<Product4Es> pageHelper =null;
        try {
            int start=(pageNum-1)*limit;
//        List<ProductByCategoryVO> list = productMapper.selectProsBySearch(start, limit, keyWord);
            SearchRequest searchRequest = new SearchRequest("fmmallproductindex");
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            //查询条件
            searchSourceBuilder.query(QueryBuilders.multiMatchQuery(keyWord,"productName"));
            //分页条件
            searchSourceBuilder.from(start);
            searchSourceBuilder.size(limit);
            //高亮显示
            HighlightBuilder highlightBuilder = new HighlightBuilder();
            HighlightBuilder.Field field = new HighlightBuilder.Field("productName");
            highlightBuilder.field(field);
            highlightBuilder.preTags("<label style='color:red'>");
            highlightBuilder.postTags("</label>");
            searchSourceBuilder.highlighter(highlightBuilder);
            searchRequest.source(searchSourceBuilder);
            SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

            SearchHits hits = response.getHits();
            int count= (int) hits.getTotalHits().value;
            List<Product4Es> products=new ArrayList<>();
            Iterator<SearchHit> iterator = hits.iterator();
            while (iterator.hasNext()){
                SearchHit searchHit = iterator.next();
                Product4Es product4Es = objectMapper.readValue(searchHit.getSourceAsString(), Product4Es.class);
                //获取高亮字段
                Map<String, HighlightField> highlightFields = searchHit.getHighlightFields();
                HighlightField highlightField = highlightFields.get("productName");
                if(highlightField!=null){
                    Text[] fragments = highlightField.getFragments();
                    String highLightProductName = Arrays.toString(fragments);
                    product4Es.setProductName(highLightProductName);
                }
                products.add(product4Es);
            }
            Example example = new Example(Product.class);
            Example.Criteria criteria = example.createCriteria();
            criteria.andLike("productName","%"+keyWord+"%");
//        int count = productMapper.selectCountByExample(example);
            int pageCounts=count%limit==0?count%limit:count%limit+1;
            pageHelper = new PageHelper<>(count,pageCounts,products);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return new ResultVO(ResStatus.OK,"success",pageHelper);
    }
}
